package com.lmk.mkcc.service.impl;


import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.lmk.mkcc.constants.CommonConstants;
import com.lmk.mkcc.constants.SmsCodeConstants;
import com.lmk.mkcc.domain.BlackPhone;
import com.lmk.mkcc.domain.MessageSms;
import com.lmk.mkcc.dto.SmsCodeDto;
import com.lmk.mkcc.enums.GlobalErrorCode;
import com.lmk.mkcc.exception.MyGlobalCustomException;
import com.lmk.mkcc.mapper.BlackPhoneMapper;
import com.lmk.mkcc.service.IMessageSmsService;
import com.lmk.mkcc.service.IVerifyCodeService;
import com.lmk.mkcc.util.AssertUtil;
import com.lmk.mkcc.util.StrUtils;
import com.lmk.mkcc.util.VerifyCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    @Autowired
    @Qualifier("redisTemplate")
    private RedisTemplate<Object,Object> redisTemplate;
    @Autowired
    private SmsCodeConstants smsCodeConstants;
    @Autowired
    private IMessageSmsService iMessageSmsService;
    @Autowired
    private BlackPhoneMapper blackPhoneMapper;


    @Override
    public String image(String imageCodeKey) {
        //生成code
        //String complexRandomString = StrUtils.getComplexRandomString(4);
        String complexRandomString = StrUtils.getRandomString(4);
        //保存到redis
        redisTemplate.opsForValue().set(imageCodeKey, complexRandomString, 5, TimeUnit.MINUTES);
        //转为base64
        String base64ImageCode = VerifyCodeUtils.verifyCode(115, 40, complexRandomString);
        return base64ImageCode;

    }

    @Override
    public void sendSmsCode(SmsCodeDto smsCodeDto) {
        /*// 获取前端传入参数
        String mobile = smsCodeDto.getMobile();
        String imageCodeKey = smsCodeDto.getRegisterImageCodeKey();
        String imageCode = smsCodeDto.getImageCode();
        //1.空值校验
        if (mobile == null){
            throw new MyGlobalCustomException(GlobalErrorCode.SERVICE_PARAM_IS_NULL);
        }
        if (imageCode == null){
            throw new MyGlobalCustomException(GlobalErrorCode.SERVICE_PARAM_IS_NULL);
        }
       if (imageCodeKey == null){
            throw new MyGlobalCustomException(GlobalErrorCode.TIMOUT_ERROE);
        }
        // 2.验证图像验证码是否过期
        Object imgObj = redisTemplate.opsForValue().get(imageCodeKey);
        if (imgObj == null) {
            //2.1.图片验证码是否过期
            throw new MyGlobalCustomException(GlobalErrorCode.TIMOUT_ERROE);
        }
        if (!imgObj.toString().equalsIgnoreCase(imageCode)) {
            //2.2.图片验证码是否正确
            throw new MyGlobalCustomException(GlobalErrorCode.CODE_ERROE);
        }
        //4.判断原来的验证码是否有效【3分钟过期 - redis】
        Object codeObj = redisTemplate.opsForValue().get("register" + mobile);

        // 如果过期或没有，就生成
        String smsCode = null;
        if (codeObj == null) {
            //如果第一次发送，redis里面没有验证码，就随机生成一个六位数的手机验证码
            smsCode = StrUtils.getRandomString(6);
        } else {
            //以前的时间
            String oldTimeTemp = codeObj.toString().split(":")[1];
            //转化为long类型
            long oldTime = Long.parseLong(oldTimeTemp);

            //获取当前时间戳
            long nowTime = System.currentTimeMillis();
            //设置发送短信的重复发送需要超过一分钟
            if ((nowTime - oldTime) < 1 * 60 * 1000) {
                //放置用户刷新页面，抛繁忙异常
                throw new MyGlobalCustomException(GlobalErrorCode.FREQUENTLY_ERROE);
            } else {
                //如果曹操过了一分钟，就获取到之前的验证码，重新发送一次
                smsCode = codeObj.toString().split(":")[0];
            }
        }
        redisTemplate.opsForValue().set("register" + mobile,
                smsCode + ":" + System.currentTimeMillis(), 3, TimeUnit.MINUTES);

        MessageSms messageSms = new MessageSms();
        messageSms.setTitle("注册验证码");
        messageSms.setContent("您的验证码为："+smsCode+"请在3分钟内使用");
        messageSms.setSendTime(new Date());
        // 获取ip
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        messageSms.setIp(request.getRemoteAddr());
        iMessageSmsService.insert(messageSms);
        log.info(messageSms.getContent());*/



        //从redis中获取黑名单对象
        //EntityWrapper<BlackPhone> wrapper = new EntityWrapper<>();
        //List<BlackPhone> blackPhones = blackPhoneMapper.selectList(wrapper);
        Object o = redisTemplate.opsForValue().get(CommonConstants.BLACK_PHONE_KEY);
        List<BlackPhone> blackPhones = (List<BlackPhone>)o;
        for (BlackPhone blackPhone:blackPhones){
            if(smsCodeDto.getMobile().equals(blackPhone.getPhone())){
                log.info("您的账号已被拉黑，请联系管理员");
                throw new MyGlobalCustomException(GlobalErrorCode.BLOCK_PHONE_ERROR);
            }
        }



        // 获取前端传入参数
        String mobile = smsCodeDto.getMobile();
        String imageCodeKey = smsCodeDto.getRegisterImageCodeKey();
        String imageCode = smsCodeDto.getImageCode();
        //1.空值校验
        AssertUtil.isPhone(mobile,GlobalErrorCode.SERVICE_PARAM_IS_NULL);
        /*if (mobile == null){
            throw new MyGlobalCustomException(GlobalErrorCode.SERVICE_PARAM_IS_NULL);
        }*/
        AssertUtil.isNotNull(imageCode,GlobalErrorCode.SERVICE_PARAM_IS_NULL);
        /*if (imageCode == null){
            throw new MyGlobalCustomException(GlobalErrorCode.SERVICE_PARAM_IS_NULL);
        }*/
        AssertUtil.isNotNull(imageCodeKey,GlobalErrorCode.TIMOUT_ERROE);
        /*if (imageCodeKey == null){
            throw new MyGlobalCustomException(GlobalErrorCode.TIMOUT_ERROE);
        }*/
        // 2.验证图像验证码是否过期
        String imgObj = redisTemplate.opsForValue().get(imageCodeKey).toString();
        AssertUtil.isNotNull(imgObj,GlobalErrorCode.TIMOUT_ERROE);
       /* if (imgObj == null) {
            //2.1.图片验证码是否过期
            throw new MyGlobalCustomException(GlobalErrorCode.TIMOUT_ERROE);
        }*/
        AssertUtil.isEquals(imgObj,imageCode,GlobalErrorCode.CODE_ERROE);
       /* if (!imgObj.toString().equalsIgnoreCase(imageCode)) {
            //2.2.图片验证码是否正确
            throw new MyGlobalCustomException(GlobalErrorCode.CODE_ERROE);
        }*/
        //4.判断原来的验证码是否有效【3分钟过期 - redis】
        String format = String.format(CommonConstants.Register_PHONE_PREFIX, mobile);
        Object codeObj = redisTemplate.opsForValue().get(format);

        // 如果过期或没有，就生成
        String smsCode = null;
        if (codeObj == null) {
            //如果第一次发送，redis里面没有验证码，就随机生成一个六位数的手机验证码
            smsCode = StrUtils.getRandomString(smsCodeConstants.getCodesize());
        } else {
            //以前的时间
            String oldTimeTemp = codeObj.toString().split(":")[1];
            //转化为long类型
            long oldTime = Long.parseLong(oldTimeTemp);
            //获取当前时间戳
            long nowTime = System.currentTimeMillis();
            //设置发送短信的重复发送需要超过一分钟
            String interval = smsCodeConstants.getInterval();
            Long value = Long.valueOf(interval);
            if ((nowTime - oldTime) < value) {
                //放置用户刷新页面，抛繁忙异常
                throw new MyGlobalCustomException(GlobalErrorCode.FREQUENTLY_ERROE);
            } else {
                //如果曹操过了一分钟，就获取到之前的验证码，重新发送一次
                smsCode = codeObj.toString().split(":")[0];
            }
        }
        //"register:"+mobile
        redisTemplate.opsForValue().set(format,
                smsCode + ":" + System.currentTimeMillis(), 3, TimeUnit.MINUTES);

        MessageSms messageSms = new MessageSms();
        messageSms.setTitle(smsCodeConstants.getSmstitle());
        String s = String.format(smsCodeConstants.getSmsmessage(), smsCode);
        messageSms.setContent(s);
        messageSms.setSendTime(new Date());
        // 获取ip
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        messageSms.setIp(request.getRemoteAddr());
        iMessageSmsService.insert(messageSms);
        log.info(messageSms.getContent());
    }


}
